package gbench.appdemo.crawler.junit.analyzer;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.junit.jupiter.api.Test;
import gbench.appdemo.crawler.analyzer.YuhuanAnalyzer;

import gbench.appdemo.crawler.analyzer.lexer.ILexProcessor;
import gbench.appdemo.crawler.analyzer.lexer.Lexeme;
import gbench.appdemo.crawler.analyzer.lexer.Trie;
import gbench.appdemo.crawler.analyzer.lexer.TrieCorpus;
import gbench.common.fs.FileSystem;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static gbench.common.tree.LittleTree.*;
import static gbench.appdemo.crawler.srch.JdbcSrchApplication.*;
import static gbench.appdemo.crawler.analyzer.YuhuanAnalyzer.*;

/**
 * 
 * @author gbench
 *
 */
public class JunitAnalyzer {
    
    /**
     * 
     */
    @Test
    public void bar() {
    
        final var keywords = "举世瞩目,奥林匹克,运动会,开幕式,北京,国家,体育馆,举行,隆重".split(",");// 关键词字典
        final var ll = Stream.of(keywords).map(e->Arrays.asList(e.split(""))).collect(Collectors.toList());
        final var trie = Trie.create(ll);
        Stream.of("举世瞩,举世瞩m".split(",")).forEach(line->{
            System.out.println(line+"-->"+trie.isPrefix(line.split("")));
        });
        // 补充语料库
        Stream.of("美丽,美利坚联合众国,美妙,美女".split(",")).forEach(keyword->{
            Trie.addPoints2Trie(trie,keyword.split(""));
        });
        
        System.out.println(trie.isPrefix("美利坚".split("")));
        System.out.println(trie.isPrefix("美利坚人民".split("")));
        Stream.of("美利坚,美利坚人民".split(",")).forEach(line->{
            System.out.println(line+"-->"+trie.isPrefix(line.split("")));
        });
        
        System.out.println("------------------------");
        System.out.println(" 语料库");
        System.out.println("------------------------");
        // 结果打印
        Trie.traverse(trie, e->{
            System.out.println(ident(e.getLevel())+e);
        });
        
        
    }


    /**
     * 语料库的 Trie 树演示
     */
    @Test
    public void foo() {
        final var line = "2008年8月8日晚，举世瞩目的北京第二十九届奥林匹克运动会开幕式在国家体育场隆重举行。Infections Worsen in 31 States; Fauci Sees No Lull: Virus Update";
        final var keywords = "举世瞩目,奥林匹克,运动会,开幕式,北京,国家,体育场,举行,隆重".split(",");// 关键词字典
        final var corpus = TrieCorpus.getCorpus(keywords);// 创建前缀树结构
        @SuppressWarnings("resource")
        final var yuhuan = new YuhuanAnalyzer().addProcessor(new ILexProcessor() { // 创建一个 分词器
            @SuppressWarnings("unused") @Override 
            public boolean isPrefix( final String line ) {
                if( Stream.of(// pattern 列表
                    "[a-zA-Z]+", // 英文单词
                    "[a-zA-Z_-]+", // 英文标识符号
                    "[\\d\\.]+", // 阿拉伯数据
                    "[一二三四五六七八九十零百千万亿兆]+",// 中文数字
                    "[一二三四五六七八九十零百千万亿兆\\d]+年([一二三四五六七八九十零百千万亿兆\\d+](月([一二三四五六七八九十零百千万亿兆\\d+]日?)?)?)?") // 日期前缀的判断
                .anyMatch(line::matches) ) return true;
                
                return true
                    ? corpus.isPrefix(line)
                    : Stream.of(keywords).anyMatch(w->w.startsWith(line));// 关键词返回true
            }// isPrefix
        });// addProcessor
        
        // 分词器演示
        Stream.of( 
                new StandardAnalyzer(), 
                yuhuan ).forEach( analyzer -> {
            System.out.println("\n -- "+analyzer.getClass().getSimpleName());
            splits(analyzer, "test", line).stream().filter(e->e.str("type").equals("word")).forEach(rec -> {
                System.out.println(rec);
            });
        });
    }
    
    /**
     * 人民代表大会的 分词测试
     */
    @Test
    public void  renmin_daibiao_dahui() {
        final var keywords = "中国,人民,中国人民,代表,大会,代表大会,人民代表大会,制度".split(",");// 关键词字典
        final var corpus = TrieCorpus.getCorpus(keywords);// 创建前缀树结构
        @SuppressWarnings("resource")
        final var yuhuan = new YuhuanAnalyzer().addProcessor(new ILexProcessor() { // 创建一个 分词器
            
            /**
             * 把符号转换成 词素
             * @param symbol 符号
             * @return 词素
             */
            @Override
            public Lexeme evaluate(String symbol) {
                return  Arrays.asList(keywords).contains(symbol) 
                        ? new Lexeme(symbol,"unknown","unknown")
                        : null;
            }
            
            @SuppressWarnings("unused") @Override 
            public boolean isPrefix( final String line ) {
                if( Stream.of(// pattern 列表
                    "[a-zA-Z]+", // 英文单词
                    "[a-zA-Z_-]+", // 英文标识符号
                    "[\\d\\.]+", // 阿拉伯数据
                    "[一二三四五六七八九十零百千万亿兆]+",// 中文数字
                    "[一二三四五六七八九十零百千万亿兆\\d]+年([一二三四五六七八九十零百千万亿兆\\d+](月([一二三四五六七八九十零百千万亿兆\\d+]日?)?)?)?") // 日期前缀的判断
                .anyMatch(line::matches) ) return true;
                
                return true
                    ? corpus.isPrefix(line)
                    : Stream.of(keywords).anyMatch(w->w.startsWith(line));// 关键词返回true
            }// isPrefix
        });// addProcessor
        
        // 分词器演示
        Stream.of( new StandardAnalyzer(), yuhuan ).forEach( analyzer -> {
                // 打印分词器名称：分词方式
                System.out.println("\n -- "+analyzer.getClass().getSimpleName());
                
                // 分词
                Stream.of("人民代表大会","人民代表大","中国人民代表","中国人民代表大会制度").forEach(line->{
                    System.out.println("-----------"+line+"-----------");
                    splits(analyzer, "test", line,false).stream().filter(e->e.str("type").equals("word")).forEach(rec -> {
                        System.out.println(rec);
                    });
                });// 分词数据 line  forEach
                
                analyzer.close();// 关闭分词器
        });// 分词器 analyzer forEach
        
    }
    
    
    /**
     * corpusPath 语料库路径
     * @return
     */
    public YuhuanAnalyzer getYuhuanAnalyzer(final String corpusDir) {
        final var corpus = new Trie<String>();// 语料库的根节点树
        final var corpusHome = new File(corpusDir);
        
        // 构建语料库
        ( ( corpusHome.isDirectory() )
            ? Stream.of(corpusHome.listFiles())
            : Stream.of(new File(FileSystem.path(corpusDir, this.getClass())))
        ).filter(file->file.getAbsolutePath().endsWith(".txt")).forEach(file->{// 创建语料文件
            FileSystem.utf8lines(file)
            .filter(line->!line.matches("^\\s*$")) // 去除空行
            .forEach(e->{// 提取语料词汇
                Stream.of(e.strip().split("[\n]+")) // 按行进行切分
                .forEach(keyword->{// 设置词素 的节点属性信息
                    final var points = keyword.split("");// 把keyword 切分乘字符点
                    Trie.addPoints2Trie(corpus, points)
                    .addAttribute("category","word")// 绑定词法类型信息
                    .addAttribute("meaning", Arrays.stream(points).collect(Collectors.joining()));
                });
            });// forEach
        });
        
        // 打印语料库
        //Trie.traverse(trie, e->System.out.println("\t".repeat(e.getLevel())+e.getValue()+"\t type:"+e.getAttribute("type")));
        
        @SuppressWarnings("resource")
        final var yuhuan = new YuhuanAnalyzer().addProcessor(new ILexProcessor() { // 创建一个 分词器
            
            /**
             * 把符号转换成 词素
             * @param symbol 符号
             * @return 词素
             */
            @Override 
            public Lexeme evaluate(final String symbol) {
                final var trieNode = corpus.getTrie(symbol.split(""));// 提取节点词素
                if(trieNode==null)return null;
                final var category = trieNode.strAttr("category");// 提取分类属性
                final var meaning = trieNode.strAttr("meaning");// 提取意义属性
                return new Lexeme(symbol,category,meaning);
            }
            
            @Override 
            public boolean isPrefix( final String line ) {
                if( Stream.of(// pattern 列表
                    "[a-zA-Z]+", // 英文单词
                    "[a-zA-Z_-]+", // 英文标识符号
                    "[\\d\\.]+", // 阿拉伯数据
                    "[一二三四五六七八九十零百千万亿兆]+",// 中文数字
                    "[一二三四五六七八九十零百千万亿兆\\d]+年([一二三四五六七八九十零百千万亿兆\\d+](月([一二三四五六七八九十零百千万亿兆\\d+]日?)?)?)?") // 日期前缀的判断
                .anyMatch(line::matches) ) return true;
                
                return corpus.isPrefix(line.split(""));
            }// isPrefix
        });// addProcessor
        
        yuhuan.setAttribute("corpus", corpus);// 设置词库竖向
        return yuhuan;
    }
    
    /**
     * 语料库的 Trie 树演示
     */
    @Test
    public void quz() {
        final var yuhuan = this.getYuhuanAnalyzer("C:\\Users\\gbench\\Desktop\\中国笔记\\逻辑词汇");
        final var ar = new AtomicInteger(0);
        traverse(new File("C:\\Users\\gbench\\Desktop\\中国笔记\\逻辑散文"), file -> {
            try (var br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf8"))) {
                br.lines().limit(5).forEach(line -> {
                    yuhuan.analyze(line).forEach(word->{
                        System.out.println(ar.getAndIncrement()+")"+word);
                    });
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}
